Unidad 3: Herramientas para el análisis exploratorio de datos


Manejo y Visualización de Datos
Maestría en Estadística Aplicada - FCEyE - UNR
Parte 2: Tipos de visualización

1 Preparativos

  • En este apunte estaremos usando el sistema gráfico de ggplot2 (¡a repasar el apunte correspondiente si es necesario!).

  • A continuación se listan los paquetes que se usan a lo largo de este material. Corriendo las siguientes líneas se pueden cargar todos, instalando los que faltan.

paquetes <-
  c("readr", "readxl", "dplyr", "tibble", "ggplot2", "cowplot", "tidyr", 
  "ggridges", "ggbeeswarm", "GGally", "rgl", "plotly", "treemapify", "car", 
  "vcd", "colorspace", "ggcleveland", "corrplot", "lubridate",
  "gganimate", "gapminder", "forcats", "janitor", "ggforce")

# Instalar si no están
instalados <- paquetes %in% rownames(installed.packages())
if (any(instalados == FALSE)) {
  install.packages(paquetes[!instalados])
}

# Cargarlos
invisible(lapply(paquetes, library, character.only = TRUE))

# Nada que ver con los paquetes, pero seteo un theme ahora para todos los plots
theme_set(theme_bw())
  • Ahora vamos a mencionar diversos diagramas y gráficos que se usan comúnmente para visualizar datos, dependiendo del objetivo que se persiga.

  • Estaremos trabajando con el conjunto de datos partos_rosario.csv, que contiene información sobre los partos atendidos en los efectores municipales de Rosario durante los años 2015 a 2018.

  • Los datos fueron descargados del Portal de Datos Abiertos de la Municipalidad de Rosario.

  • Las variables disponibles son1:

    • año: año del parto
    • mes: mes del parto
    • efector: Hospital Roque Sáenz Peña (HRSP) o Maternidad Martin (MM).
    • idmama: código de identificación de la madre
    • idparto: código de identificación del parto
    • edad_madre: edad de la madre en años
    • rango_edad: edad de la madre categorizada en intervalos quinquenales
    • rango_edad2: edad de la madre categorizada en intervalos de 10 años
    • hijo: número que identifica a cada hijo nacido en el parto
    • lugar: lugar donde ocurrió el parto
    • parto: tipo de parto
    • edad_gestacional_valor: edad gestacional categorizada del recién nacido en semanas completas
    • edad_gestacional: edad gestacional categorizada del recién nacido en semanas completas, categorizada en intervalos.
    • peso: peso en gramos del recién nacido
    • sexo_bb: sexo del recién nacido (femenino = F, masculino = M)
  • Procedemos a la lectura del archivo:
datos <- read_csv("partos_rosario.csv")
  • Previsualización:
datos
# A tibble: 20,943 × 15
     año   mes efector idmama idparto edad_madre rango_edad   rango_edad2  hijo
   <dbl> <dbl> <chr>    <dbl>   <dbl>      <dbl> <chr>        <chr>       <dbl>
 1  2015     9 MM        2082    2084         11 10 a 14 años 10 a 19         1
 2  2015    10 MM        2974    2976         12 10 a 14 años 10 a 19         1
 3  2015     7 MM        2550    2552         14 10 a 14 años 10 a 19         1
 4  2015     3 MM        5137    5139         13 10 a 14 años 10 a 19         1
 5  2015     8 MM        5241    5243         10 10 a 14 años 10 a 19         1
 6  2015     9 MM        5438    5440         10 10 a 14 años 10 a 19         1
 7  2015     3 HRSP       195     195         14 10 a 14 años 10 a 19         1
 8  2015     5 HRSP       230     230         14 10 a 14 años 10 a 19         1
 9  2015     4 HRSP       533     534         14 10 a 14 años 10 a 19         1
10  2015     9 HRSP       570     571         13 10 a 14 años 10 a 19         1
# … with 20,933 more rows, and 6 more variables: lugar <chr>, parto <chr>,
#   edad_gestacional_valor <dbl>, edad_gestacional <chr>, peso <dbl>,
#   sexo_bb <chr>

2 Otras visualizaciones

2.1 Visualización en paneles (faceting)

  • La visualización en paneles consiste en repetir el mismo gráfico para cada nivel de una variable adicional, o para cada combinación de niveles de más de una variable.
  • Es un medio que permite aumentar rápidamente el número de variables visualizadas en una figura.
ggplot(datos) +
  aes(x = rango_edad2, y = peso) +
  geom_boxplot() +
  facet_wrap(~ edad_gestacional, nrow = 1, 
             labeller = labeller(edad_gestacional = function(x) paste(x, "semanas"))) +
    labs(x = "Edad de la madre", y = "Peso (g)",
             title = "Peso de nacimiento\nsegún edad de la madre y semanas de gestación") +
    theme(axis.text.x = element_text(angle = 45, hjust = 1))

  • En el siguiente ejemplo se usan dos variables para definir los paneles:
ggplot(datos) +
  aes(x = rango_edad2, y = peso) +
  geom_boxplot() +
  facet_grid(parto ~ edad_gestacional,
             labeller = labeller(edad_gestacional = function(x) paste(x, "semanas"))) +
    labs(x = "Edad de la madre", y = "Peso (g)",
             title = "Peso de nacimiento\nsegún edad de la madre, semanas de gestación y tipo de parto") +
    theme(axis.text.x = element_text(angle = 45, hjust = 1))

  • A continuación vemos que no es necesario disponer los paneles en múltiples filas para mostrar la combinación de niveles entre dos variables:
ggplot(datos) +
  aes(x = rango_edad2, y = peso) +
  geom_boxplot() +
  facet_grid(. ~ parto + sexo_bb) +
  labs(x = "Edad de la madre", y = "Peso (g)",
       title = "Peso de nacimiento según edad de la madre,\ntipo de parto y sexo del recién nacido") + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

  • Finalmente, vemos que las ideas anteriores pueden extenderse para separar en paneles teniendo en cuenta más de dos variables:
ggplot(datos) +
  aes(x = rango_edad2, y = peso) +
  geom_boxplot() +
  facet_grid(edad_gestacional ~ parto + sexo_bb) +
    labs(x = "Edad de la madre", y = "Peso (g)",
             title = "Peso de nacimiento según edad de la madre,\ntipo de parto, edad gestacional y sexo del recién nacido") +
    theme(axis.text.x = element_text(angle = 45, hjust = 1))

2.2 Paquete plotly

  • Plotly es una compañía canadiense fundada en 2013 que ofrece herramientas de visualización y data analytics (link a su web oficial) asociadas generalmente a lenguajes de programación como Python o JavaScript. Entre los muchos productos desarrollados por esta empresa se encuentra el paquete de R que lleva su nombre, orientado a generar visualizaciones dinámicas (link a las referencias).

  • Si bien este paquete ofrece numerosas posibilidades (ver galería) no todos tenemos tiempo para aprender a generar gráficos con una nueva sintaxis, lo que implicaría acostumbrarse a escribir nuevas estructuras, funciones, argumentos, opciones, etc. Por suerte para nosotros, plotly se integra perfectamente con nuestro viejo conocido ggplot2 de manera muy simple.

datos_sub <- datos[1:500,]

# Creamos un gráfico de ggplot común y corriente
grafico <- 
  ggplot(datos_sub) +
  aes(x = edad_gestacional_valor, y = peso, color = parto) +
  geom_jitter(width = 0.5, height = 0, alpha = 0.5) +
  labs(x = "Edad gestacional (semanas completas)", y = "Peso (g)",
       color = "Tipo de parto")
grafico

# Y lo convertimos en uno de plotly
ggplotly(grafico)
# Para controlar lo que aparece como texto al pasar sobre los puntos:
datos_sub <- mutate(datos_sub, 
                    etiqueta = paste0("Efector: ", efector, "\nEdad madre: ", edad_madre))

# Usamos la estética text
grafico <- 
  ggplot(datos_sub) +
  aes(x = edad_gestacional_valor, y = peso, color = parto, text = etiqueta) +
  geom_jitter(width = 0.5, height = 0, alpha = 0.5) +
  labs(x = "Edad gestacional (semanas completas)", y = "Peso (g)",
       color = "Tipo de parto")

# Muestra la info de todas las estéticas definidas
ggplotly(grafico)
# Muestra la info de las estéticas especificadas en tooltip
ggplotly(grafico, tooltip = "text")

2.3 Paquete gganimate

  • gganimate es una extensión de ggplot2 que ofrece herramientas para crear gráficos animados a partir de objetos ggplot. Este paquete es útil cuando queremos representar en un mismo gráfico diferentes períodos temporales, o bien destacar las diferencias entre distintos grupos de individuos.

  • Veamos un ejemplo donde se aprecia la evolución a través de los años del PBI per cápita y la esperanza de vida de varios países según continente, tomando datos del paquete gapminder.

  • Los pasos a seguir para generar una animación en formato gif son:

    • Crear un gráfico de manera corriente con ggplot y agregar una capa extra con alguna de las funciones transition de gganimate, la cual crea un gráfico diferente para cada valor de la variable establecida
    • Generar un objeto “animado” mediante la función animate(), eligiendo la cantidad de fotogramas
    • Guardar el objeto animado en un archivo en nuestra PC, con formato gif, utilizando la función anim_save()
# Hacemos un gráfico básico
g <- 
  ggplot(data = gapminder) +
  aes(x = log(gdpPercap), y = lifeExp, size = pop, colour = country) +
  geom_point(alpha = 0.7, show.legend = FALSE)
g

# Imaginar cada paso de la animación como algo que se podría graficar en paneles...
g + facet_wrap(~year)

# Entonces sólo tenemos que intercambiar la capa de paneles por una de
# transición animada
g + transition_time(year)

  • Ahora le agregamos algunos detalles, usamos la función animate() para especificar opciones referidas a la generación del gif (cantidad de frames, duración, etc.) y la función anim_save() para guardar un archivo con la animación:
g <- 
  ggplot(data = gapminder) +
  aes(x = log(gdpPercap), y = lifeExp, size = pop, colour = country) +
  geom_point(alpha = 0.7, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  facet_wrap(~continent) +
  labs(title = 'Año: {frame_time}', 
       x = 'Logaritmo del PBI per Cápita', 
       y = 'Esperanza de Vida (en años)') +
  theme_bw() +
  theme(axis.title = element_text(face = "bold")) +
  transition_time(year) + #Variable de Transición
  ease_aes('linear') #Tipo de Transición

animacion <- animate(Grafico, 
                     renderer = gifski_renderer(), 
                     nframes = 50) # Cantidad de fotogramas

# Guardo la animación en un archivo formato gif
anim_save(filename = "Gapminder.gif",
          animation = animacion)
Gráfico animado con gganimate según año

Gráfico animado con gganimate según año

  • Otro ejemplo:

2.4 Visualizaciones en 3D

  • Si bien hoy existen muchos paquetes de software que facilitan la visualización de datos trivariados, no debe olvidarse que de todas formas el resultado para nuestra vista es siempre una representación en dos dimensiones y su interpretación es altamente dependiente del ángulo elegido.

  • Por eso, muchos autores no recomiendan su uso.

  • ggplot2 por sí solo no posee la capacidad de renderizar gráficos dinámicos en 3D.

  • Una opción es el paquete rgl:

  • Otra alternativa es el paquete plotly.

  • Link a referencias para diagramas de dispersión en 3D).

plot_ly(data = datos_sub, 
        x = ~edad_gestacional_valor, 
        y = ~edad_madre, 
        z = ~peso, 
        type = "scatter3d", mode = "markers", size = 0.5) %>% 
  layout(
    scene = list(
      xaxis = list(title = "Edad gestacional (semanas)"),
      yaxis = list(title = "Edad de la madre (años)"),
      zaxis = list(title = "Peso (g)")
  ))

  1. En los datos originales, sólo está disponible la edad de la madre en agrupada en quinquenios y la edad gestacionales en intervalos de semanas. Con fines didácticos se simularon los valores cuantitativos edad_madre y edad_gestacional_valor. Además, se eliminaron casos sensibles de edades gestacionales pequeñas.↩︎